import { Injectable, Optional, NgZone } from '@angular/core';
import { Overlay, PositionStrategy, FlexibleConnectedPositionStrategy, ConnectionPositionPair } from '@angular/cdk/overlay';
import { ComponentPortal, PortalInjector } from '@angular/cdk/portal';
import { ColumnCustomComponent } from '../../common/column-custom/column-custom.component';
import { ColumnCustomState } from '../column-custom-state';
import { Base } from '../view/base';
import { I18nService } from '../i18n/i18n.service';

@Injectable({
  providedIn: 'root'
})
export class DataGridColumnCustomService<U, B, S> extends Base<U, B, S> {

  /** 将数据临时保存在sessionStorage中，避免频繁请求接口 */
  private columnCustomPrefix = 'CUSTOM_COL_';

  constructor(
    private overlay: Overlay,
    private i18n: I18nService,
    @Optional() private columnCustomState: ColumnCustomState
  ) {
    super();
  }

  /**
   * dataGrid添加自定义列功能
   */
  columnCustom(dataGrid: any) {
    const dataGridEle = dataGrid.instance.element();
    const dataGridName = dataGridEle.getAttribute('name');
    if (dataGrid._columnCustom || !dataGridName) {
      if (!dataGridName) {
        this.loggerService.warn('dataGrid attr name can not be null');
      }
      return;
    }

    dataGrid._columnCustom = true;
    this._columnCustomInit(dataGrid);
    this._columnCustomLoad(dataGrid, dataGridName);
  }

  /** 初始化配置按钮图标 */
  private _columnCustomInit(dataGrid: any) {
    const dataGridEle = dataGrid.instance.element();
    const dataGridName = dataGridEle.getAttribute('name');
    const dataGridContainerEle = dataGridEle.querySelector('.dx-datagrid');
    const dataGridHeadersEle = dataGridEle.querySelector('.dx-datagrid-headers');
    const dataGridTDEle = dataGridHeadersEle.querySelector('.dx-datagrid-content:not(.dx-datagrid-content-fixed) td');
    if (!dataGridContainerEle || !dataGridHeadersEle || !dataGridTDEle) {
      this.loggerService.warn('dataGrid not the expected structure');
      return;
    }

    // const dataGridHeadersStyles = window.getComputedStyle(dataGridHeadersEle);
    // const dataGridTDStyles = window.getComputedStyle(dataGridTDEle);
    // const headerHeight = (Number(dataGridHeadersStyles.getPropertyValue('height')) || 40) + 'px';
    // const headerBgColor = dataGridTDStyles.getPropertyValue('background-color');

    dataGridHeadersEle.classList.add('column-custom');

    // 创建提示浮层
    const columnOptionTitleEle = document.createElement('div');
    const columnOptionTitleArrowEle = document.createElement('i');
    columnOptionTitleArrowEle.style.cssText = `
      position: absolute;
      right: 15px;
      top: 26px;
      background-color: rgb(51, 51, 51);
      width: 12px;
      height: 12px;
      transform: rotate(45deg);
    `;
    columnOptionTitleEle.style.cssText = `
      position: absolute;
      right: 0;
      top: -35px;
      display: none;
      width: 100px;
      background-color: #333;
      font-size: 12px;
      height: 32px;
      line-height: 32px;
      color: #fff;
      border-radius: 4px;
    `;
    columnOptionTitleEle.appendChild(columnOptionTitleArrowEle);
    columnOptionTitleEle.innerHTML += this.i18n.getValue('@custom-header', 'core');

    // 创建图标元素
    const columnOptionIconEle = document.createElement('i');
    columnOptionIconEle.className = 'unex unex-icon-setting';
    columnOptionIconEle.style.verticalAlign = 'baseline';

    // 创建图标父容器
    const columnOptionEle = document.createElement('div');
    // const dataGridHeadersStyles = window.getComputedStyle(dataGridHeadersEle);
    // const dataGridTDStyles = window.getComputedStyle(dataGridTDEle);
    // const headerHeight = (Number(dataGridHeadersStyles.getPropertyValue('height')) || 40) + 'px';
    // const headerBgColor = dataGridTDStyles.getPropertyValue('background-color');
    columnOptionEle.style.cssText = `
      position: absolute;
      top: 1px;
      right: 0;
      padding: 0 5px;
      z-index: 1000;
      line-height: 40px;
      height: 40px;
      background-color: #f5f5f5;
      cursor: pointer;
      text-align: center;
      width: 40px;
    `;
    columnOptionEle.appendChild(columnOptionTitleEle);
    columnOptionEle.appendChild(columnOptionIconEle);
    dataGridContainerEle.appendChild(columnOptionEle);

    // 图标添加点击事件
    this.ngZone.runOutsideAngular(() => {
      columnOptionEle.addEventListener('click', this._columnCustomOnClick.bind(this, columnOptionEle, dataGrid, dataGridName));
      columnOptionEle.addEventListener('mousemove', this._columnCustomOnMousemove.bind(this, columnOptionEle, columnOptionTitleEle));
      columnOptionEle.addEventListener('mouseout', this._columnCustomOnMouseout.bind(this, columnOptionEle, columnOptionTitleEle));
    });
  }

  // 图标按钮鼠标移入事件
  private _columnCustomOnMousemove(columnOptionEle: HTMLElement, columnOptionTitleEle: HTMLElement) {
    columnOptionEle.style.cssText += 'color:#3366FF;background-color: #E8E8E8;';
    columnOptionTitleEle.style.display = 'inline-block';
  }
  // 图标按钮鼠标移出事件
  private _columnCustomOnMouseout(columnOptionEle: HTMLElement, columnOptionTitleEle: HTMLElement) {
    columnOptionEle.style.cssText += 'color:unset;background-color: #f5f5f5;';
    columnOptionTitleEle.style.display = 'none';
  }

  // 图标按钮点击事件，动态创建悬浮层
  private _columnCustomOnClick(columnOptionEle: HTMLElement, dataGrid: any, dataGridName: string) {
    // 设定悬浮层定位策略
    const positionStrategy = this.overlay.position()
      .flexibleConnectedTo(columnOptionEle)
      .withPositions([
        new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'top' })
      ]);
    // 创建悬浮层
    const overlayRef = this.overlay.create({
      hasBackdrop: true,
      positionStrategy: positionStrategy
    });
    // 添加悬浮层背景层点击事件
    overlayRef.backdropClick().subscribe(() => {
      overlayRef.dispose();
    });
    // 动态创建组件
    const columnCustomPortal = new ComponentPortal(ColumnCustomComponent);
    // 添加组件到悬浮层中
    const componentRef = overlayRef.attach(columnCustomPortal).instance;
    // 设置附件属性和方法
    componentRef.list = dataGrid.columns.filter((col) => {
      return col.dataField && col.caption;
    }).map((col) => {
      return {
        key: col.dataField,
        name: col.caption,
        checked: dataGrid.instance.columnOption(col.dataField, 'visible') !== false
      };
    });
    componentRef.dataGridName = dataGridName;
    // 当组件中点击确定按钮或者重置按钮时的执行保存操作
    componentRef._setColumn = (showCols) => {
      overlayRef.dispose();
      if (Array.isArray(showCols) && showCols.length > 0) {
        this._columnCustomSave(showCols, dataGridName);
        // 强制更新
        this.ngZone.run(() => {
          this._setColumnCustom(dataGrid, showCols);
        });
      }
    };
  }

  /** 保存自定义配置 */
  private _columnCustomSave(showCols: string[], dataGridName: string) {
    const key = `${this.currPath()}||${dataGridName}`;
    const sessionStorekey = `${this.columnCustomPrefix}||${key}`;
    this.storeService.setItemByUID(<any>sessionStorekey, showCols, true);
    if (this.columnCustomState) {
      this.columnCustomState.saveColumnState(key, showCols);
    }
  }

  /** 加载自定义配置 */
  private _columnCustomLoad(dataGrid: any, dataGridName: string) {
    const key = `${this.currPath()}||${dataGridName}`;
    const sessionStorekey = `${this.columnCustomPrefix}||${key}`;
    new Promise((resolve, reject) => {
      // 首先从sessionStorage中读取自定义配置，如果找不到才会从后台获取数据
      const showCols = this.storeService.getItemByUID(<any>sessionStorekey, true);
      // 优先考虑sessionStorage中的数据
      if (Array.isArray(showCols) && showCols.length > 0) {
        resolve(showCols);
      } else if (this.columnCustomState) {// 通过接口保存数据
        this.columnCustomState.fetchColumnState(key).then((list) => {
          if (Array.isArray(list) && list.length > 0) {
            this.storeService.setItemByUID(<any>sessionStorekey, list, true);
          } else {
            list = [];
          }
          resolve(list);
        });
      }
    }).then(this._setColumnCustom.bind(this, dataGrid));
  }

  /** 设置dataGrid列显示隐藏 */
  private _setColumnCustom(dataGrid: any, showCols: string[]) {
    if (!Array.isArray(showCols) || showCols.length <= 0) {
      return;
    }

    dataGrid.columns.filter((col) => {
      return col.dataField && col.caption;
    }).forEach((col) => {
      const visible = showCols.includes(col.dataField);
      if (visible !== col.visible) {
        dataGrid.instance.columnOption(col.dataField, 'visible', visible);
      }
    });
  }

}
